tables can be sorted; optimized Agents load slightly

Andrew Cantino 10 years ago
parent
commit
77723a91d5

+ 0 - 9
app/assets/stylesheets/application.css.scss.erb

@@ -36,15 +36,6 @@ body { padding-top: 60px; }
36 36
   @extend .control-group.error;
37 37
 }
38 38
 
39
-table.events {
40
-  .payload {
41
-    color: #999;
42
-    font-size: 12px;
43
-    //text-align: center;
44
-    font-family: monospace;
45
-  }
46
-}
47
-
48 39
 .select2 {
49 40
   float: none !important;
50 41
   margin-left: 0 !important;

+ 31 - 0
app/assets/stylesheets/tables.css.scss

@@ -0,0 +1,31 @@
1
+// Sortable table headers
2
+.table th a.selected {
3
+  position: relative;
4
+  text-decoration: underline;
5
+
6
+  &.asc:after, &.desc:after {
7
+    text-decoration: none;
8
+    position: absolute;
9
+    top: -5px;
10
+    right: -12px;
11
+    font-size: 1.2em;
12
+  }
13
+
14
+  &.asc:after {
15
+    content: '\2193';
16
+  }
17
+
18
+  &.desc:after {
19
+    content: '\2191';
20
+  }
21
+}
22
+
23
+table.events {
24
+  .payload {
25
+    color: #999;
26
+    font-size: 12px;
27
+    //text-align: center;
28
+    font-family: monospace;
29
+  }
30
+}
31
+

+ 4 - 1
app/controllers/agents_controller.rb

@@ -1,8 +1,11 @@
1 1
 class AgentsController < ApplicationController
2 2
   include DotHelper
3
+  include SortableTable
3 4
 
4 5
   def index
5
-    @agents = current_user.agents.page(params[:page])
6
+    set_table_sort sorts: %w[name last_check_at last_event_at last_receive_at], default: { name: :asc }
7
+
8
+    @agents = current_user.agents.preload(:scenarios, :controllers).reorder(table_sort).page(params[:page])
6 9
 
7 10
     respond_to do |format|
8 11
       format.html

+ 53 - 0
app/controllers/concerns/sortable_table.rb

@@ -0,0 +1,53 @@
1
+require 'active_support/concern'
2
+
3
+module SortableTable
4
+  extend ActiveSupport::Concern
5
+
6
+  included do
7
+    helper SortableTableHelper
8
+  end
9
+
10
+  protected
11
+
12
+  def table_sort
13
+    raise("You must call set_table_sort in any action using table_sort.") unless @table_sort_info.present?
14
+    @table_sort_info[:order]
15
+  end
16
+
17
+  def set_table_sort(sort_options)
18
+    valid_sorts = sort_options[:sorts] || raise("You must specify :sorts as an array of valid sort attributes.")
19
+    default = sort_options[:default] || { valid_sorts.first.to_sym => :desc }
20
+
21
+    if params[:sort].present?
22
+      attribute, direction = params[:sort].downcase.split('.')
23
+      unless valid_sorts.include?(attribute)
24
+        attribute, direction = default.to_a.first
25
+      end
26
+    else
27
+      attribute, direction = default.to_a.first
28
+    end
29
+
30
+    direction = direction.to_s == 'desc' ? 'desc' : 'asc'
31
+
32
+    @table_sort_info = {
33
+      order: { attribute.to_sym => direction.to_sym },
34
+      attribute: attribute,
35
+      direction: direction
36
+    }
37
+  end
38
+
39
+  module SortableTableHelper
40
+    def sortable_column(attribute, name = attribute.humanize, default_direction = 'desc')
41
+      selected = @table_sort_info[:attribute].to_s == attribute
42
+      if selected
43
+        direction = @table_sort_info[:direction]
44
+        new_direction = direction.to_s == 'desc' ? 'asc' : 'desc'
45
+        classes = "selected #{direction}"
46
+      else
47
+        classes = ''
48
+        new_direction = default_direction
49
+      end
50
+      link_to(name, url_for(sort: "#{attribute}.#{new_direction}"), class: classes)
51
+    end
52
+  end
53
+end

+ 7 - 2
app/controllers/scenarios_controller.rb

@@ -1,8 +1,11 @@
1 1
 class ScenariosController < ApplicationController
2
+  include SortableTable
2 3
   skip_before_filter :authenticate_user!, :only => :export
3 4
 
4 5
   def index
5
-    @scenarios = current_user.scenarios.page(params[:page])
6
+    set_table_sort sorts: %w[name public], default: { name: :asc }
7
+
8
+    @scenarios = current_user.scenarios.reorder(table_sort).page(params[:page])
6 9
 
7 10
     respond_to do |format|
8 11
       format.html
@@ -21,7 +24,9 @@ class ScenariosController < ApplicationController
21 24
 
22 25
   def show
23 26
     @scenario = current_user.scenarios.find(params[:id])
24
-    @agents = @scenario.agents.preload(:scenarios).page(params[:page])
27
+
28
+    set_table_sort sorts: %w[name last_check_at last_event_at last_receive_at], default: { name: :asc }
29
+    @agents = @scenario.agents.preload(:scenarios, :controllers).reorder(table_sort).page(params[:page])
25 30
 
26 31
     respond_to do |format|
27 32
       format.html

+ 5 - 1
app/controllers/services_controller.rb

@@ -1,8 +1,12 @@
1 1
 class ServicesController < ApplicationController
2
+  include SortableTable
3
+
2 4
   before_filter :upgrade_warning, only: :index
3 5
 
4 6
   def index
5
-    @services = current_user.services.page(params[:page])
7
+    set_table_sort sorts: %w[provider name global], default: { provider: :asc }
8
+
9
+    @services = current_user.services.reorder(table_sort).page(params[:page])
6 10
 
7 11
     respond_to do |format|
8 12
       format.html

+ 5 - 1
app/controllers/user_credentials_controller.rb

@@ -1,6 +1,10 @@
1 1
 class UserCredentialsController < ApplicationController
2
+  include SortableTable
3
+
2 4
   def index
3
-    @user_credentials = current_user.user_credentials.page(params[:page])
5
+    set_table_sort sorts: %w[credential_name credential_value], default: { credential_name: :asc }
6
+
7
+    @user_credentials = current_user.user_credentials.reorder(table_sort).page(params[:page])
4 8
 
5 9
     respond_to do |format|
6 10
       format.html

+ 1 - 1
app/helpers/agent_helper.rb

@@ -31,7 +31,7 @@ module AgentHelper
31 31
   end
32 32
 
33 33
   def agent_controllers(agent, delimiter = ', ')
34
-    unless agent.controllers.empty?
34
+    if agent.controllers.present?
35 35
       agent.controllers.map { |agent|
36 36
         link_to(agent.name, agent_path(agent))
37 37
       }.join(delimiter).html_safe

+ 4 - 4
app/views/agents/_table.html.erb

@@ -1,11 +1,11 @@
1 1
 <div class='table-responsive'>
2 2
   <table class='table table-striped'>
3 3
     <tr>
4
-      <th>Name</th>
4
+      <th><%= sortable_column 'name', 'Name', 'asc' %></th>
5 5
       <th>Schedule</th>
6
-      <th>Last Check</th>
7
-      <th>Last Event Out</th>
8
-      <th>Last Event In</th>
6
+      <th><%= sortable_column 'last_check_at', 'Last Check' %></th>
7
+      <th><%= sortable_column 'last_event_at', 'Last Event Out' %></th>
8
+      <th><%= sortable_column 'last_receive_at', 'Last Event In' %></th>
9 9
       <th>Events Created</th>
10 10
       <th>Working?</th>
11 11
       <th></th>

+ 2 - 2
app/views/scenarios/index.html.erb

@@ -12,9 +12,9 @@
12 12
 
13 13
       <table class='table table-striped'>
14 14
         <tr>
15
-          <th>Name</th>
15
+          <th><%= sortable_column 'name', 'Name', 'asc' %></th>
16 16
           <th>Agents</th>
17
-          <th>Public</th>
17
+          <th><%= sortable_column 'public' %></th>
18 18
           <th></th>
19 19
         </tr>
20 20
 

+ 3 - 3
app/views/services/index.html.erb

@@ -25,9 +25,9 @@
25 25
       <div class='table-responsive'>
26 26
         <table class='table table-striped events'>
27 27
           <tr>
28
-            <th>Provider</th>
29
-            <th>Username</th>
30
-            <th>Global?</th>
28
+            <th><%= sortable_column 'provider', 'Provider', 'asc' %></th>
29
+            <th><%= sortable_column 'name', 'Name', 'asc' %></th>
30
+            <th><%= sortable_column 'global', 'Global?' %></th>
31 31
             <th></th>
32 32
           </tr>
33 33
 

+ 2 - 2
app/views/user_credentials/index.html.erb

@@ -14,8 +14,8 @@
14 14
 
15 15
       <table class='table table-striped'>
16 16
         <tr>
17
-          <th>Name</th>
18
-          <th>Value</th>
17
+          <th><%= sortable_column 'credential_name', 'Name', 'asc' %></th>
18
+          <th><%= sortable_column 'credential_value', 'Value', 'asc' %></th>
19 19
         </tr>
20 20
 
21 21
         <% @user_credentials.each do |user_credential| %>

+ 61 - 0
spec/controllers/concerns/sortable_table_spec.rb

@@ -0,0 +1,61 @@
1
+require 'spec_helper'
2
+
3
+describe SortableTable do
4
+  class SortableTestController
5
+    attr_accessor :params
6
+
7
+    def self.helper(foo)
8
+    end
9
+
10
+    include SortableTable
11
+
12
+    public :set_table_sort
13
+    public :table_sort
14
+  end
15
+
16
+  describe "#set_table_sort" do
17
+    let(:controller) { SortableTestController.new }
18
+    let(:default) { { column2: :asc }}
19
+    let(:options) { { sorts: %w[column1 column2], default: default } }
20
+
21
+    it "uses a default when no sort is given" do
22
+      controller.params = {}
23
+      controller.set_table_sort options
24
+      controller.table_sort.should == default
25
+    end
26
+
27
+    it "applies the given sort when one is passed in" do
28
+      controller.params = { sort: "column1.desc" }
29
+      controller.set_table_sort options
30
+      controller.table_sort.should == { column1: :desc }
31
+
32
+      controller.params = { sort: "column1.asc" }
33
+      controller.set_table_sort options
34
+      controller.table_sort.should == { column1: :asc }
35
+
36
+      controller.params = { sort: "column2.desc" }
37
+      controller.set_table_sort options
38
+      controller.table_sort.should == { column2: :desc }
39
+    end
40
+
41
+    it "ignores unknown directions" do
42
+      controller.params = { sort: "column1.foo" }
43
+      controller.set_table_sort options
44
+      controller.table_sort.should == { column1: :asc }
45
+
46
+      controller.params = { sort: "column1.foo drop tables" }
47
+      controller.set_table_sort options
48
+      controller.table_sort.should == { column1: :asc }
49
+    end
50
+
51
+    it "ignores unknown columns" do
52
+      controller.params = { sort: "foo.asc" }
53
+      controller.set_table_sort options
54
+      controller.table_sort.should == default
55
+
56
+      controller.params = { sort: ";drop table;.asc" }
57
+      controller.set_table_sort options
58
+      controller.table_sort.should == default
59
+    end
60
+  end
61
+end

+ 2 - 0
spec/spec_helper.rb

@@ -55,6 +55,8 @@ RSpec.configure do |config|
55 55
   config.global_fixtures = :all
56 56
   config.treat_symbols_as_metadata_keys_with_true_values = true
57 57
 
58
+  config.render_views
59
+
58 60
   config.include Devise::TestHelpers, :type => :controller
59 61
   config.include SpecHelpers
60 62
   config.include Delorean